/*
    Copyright (C) 2013 maik.jablonski@jease.org

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package jfix.util;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.nio.channels.FileChannel;

/**
 * Utilitities to ease the handling of java.io.File.
 */
public class Files {

	/**
	 * Creates a new file (and missing parent folders) if given file doesn't
	 * exist. If something goes wrong, a thrown IOException is wrapped within a
	 * RuntimeException.
	 */
	public static void createMissing(File file) {
		if (!file.exists()) {
			try {
				file.getParentFile().mkdirs();
				file.createNewFile();
			} catch (java.io.IOException e) {
				throw new RuntimeException(e.getMessage(), e);
			}
		}
	}

	/**
	 * Creates a temporary directory. If something goes wrong, a thrown
	 * IOException is wrapped within a RuntimeException.
	 */
	public static File createTempDirectory() {
		try {
			File directory = File.createTempFile("jfix-util-", "");
			directory.delete();
			directory.mkdirs();
			return directory;
		} catch (java.io.IOException e) {
			throw new RuntimeException(e.getMessage(), e);
		}
	}

	/**
	 * Renames given source to target. If File#renameTo(File) fails, the file
	 * content is copied from source to target.
	 */
	public static void rename(File source, File target) {
		target.delete();
		if (!source.renameTo(target)) {
			copy(source, target);
			source.delete();
		}
	}

	/**
	 * Copies source to target via NIO API. If source is null or doesn't exist,
	 * nothing happens.
	 */
	public static void copy(File source, File target) {
		if (source != null && source.exists()) {
			try {
				target.createNewFile();
				FileChannel sourceChannel = new FileInputStream(source)
						.getChannel();
				FileChannel targetChannel = new FileOutputStream(target)
						.getChannel();
				targetChannel.transferFrom(sourceChannel, 0,
						sourceChannel.size());
				sourceChannel.close();
				targetChannel.close();
			} catch (IOException e) {
				throw new RuntimeException(String.format(
						"Copy file from '%s' to '%s' failed (%s)",
						source.getAbsolutePath(), target.getAbsolutePath(),
						e.getMessage()), e);
			}
		}
	}

	/**
	 * Returns UTF-8 encoded Reader for given file.
	 */
	public static Reader newReader(File file) throws IOException {
		try {
			return new BufferedReader(new InputStreamReader(
					new FileInputStream(file), "UTF-8"));
		} catch (Exception e) {
			throw new IOException(e);
		}
	}

	/**
	 * Returns UTF-8 encoded Writer for given file.
	 */
	public static Writer newWriter(File file) throws IOException {
		try {
			return new BufferedWriter(new OutputStreamWriter(
					new FileOutputStream(file), "UTF-8"));
		} catch (Exception e) {
			throw new IOException(e);
		}
	}

}
